{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 自动量化实现常用函数和类\n",
    "\n",
    "参考：`tvm/src/relay/quantize/realize.cc`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/media/pc/data/lxw/ai/tvm-book/doc/read/relay\n"
     ]
    }
   ],
   "source": [
    "%cd ..\n",
    "import testing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## QRealizeExprNode & QRealizeExpr\n",
    "\n",
    "```c++\n",
    "class QRealizeExprNode : public TempExprNode {\n",
    " public:\n",
    "  Expr data;\n",
    "  static constexpr const char* _type_key = \"relay.quantize.QRealizeExpr\";\n",
    "  TVM_DECLARE_BASE_OBJECT_INFO(QRealizeExprNode, TempExprNode);\n",
    "};\n",
    "\n",
    "class QRealizeExpr : public TempExpr {\n",
    " public:\n",
    "  TVM_DEFINE_OBJECT_REF_METHODS(QRealizeExpr, TempExpr, QRealizeExprNode);\n",
    "};\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是两个C++类的定义，它们分别表示量化表达式节点和量化表达式。\n",
    "\n",
    "1. `QRealizeExprNode` 类继承自 `TempExprNode` 类，表示一个量化表达式节点。它包含一个 `Expr` 类型的成员变量 `data`，用于存储量化表达式的数据。同时，它还定义了一个静态常量字符串 `_type_key`，用于表示该类的类型信息。此外，它还使用了 `TVM_DECLARE_BASE_OBJECT_INFO` 宏来声明基类对象的信息。\n",
    "\n",
    "2. `QRealizeExpr` 类继承自 `TempExpr` 类，表示一个量化表达式。它使用了 `TVM_DEFINE_OBJECT_REF_METHODS` 宏来定义对象引用方法，该方法将 `QRealizeExpr` 类与 `QRealizeExprNode` 类关联起来。这样，可以通过 `QRealizeExpr` 对象间接访问和操作 `QRealizeExprNode` 对象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## QRealizeIntExprNode & QRealizeIntExpr\n",
    "\n",
    "````{dropdown}\n",
    "```c++\n",
    "class QRealizeIntExprNode : public QRealizeExprNode {\n",
    " public:\n",
    "  Expr dom_scale;\n",
    "  DataType dtype;\n",
    "\n",
    "  void VisitAttrs(tvm::AttrVisitor* v) {\n",
    "    v->Visit(\"data\", &data);\n",
    "    v->Visit(\"dom_scale\", &dom_scale);\n",
    "    v->Visit(\"dtype\", &dtype);\n",
    "  }\n",
    "\n",
    "  Expr Realize() const final;\n",
    "\n",
    "  static constexpr const char* _type_key = \"relay.quantize.QRealizeIntExpr\";\n",
    "  TVM_DECLARE_FINAL_OBJECT_INFO(QRealizeIntExprNode, QRealizeExprNode);\n",
    "};\n",
    "\n",
    "class QRealizeIntExpr : public QRealizeExpr {\n",
    " public:\n",
    "  TVM_DLL QRealizeIntExpr(Expr data, Expr dom_scale, DataType dtype);\n",
    "\n",
    "  TVM_DEFINE_OBJECT_REF_METHODS(QRealizeIntExpr, QRealizeExpr, QRealizeIntExprNode);\n",
    "};\n",
    "```\n",
    "````"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是两个C++类的定义，它们分别表示量化整数表达式节点和量化整数表达式。\n",
    "\n",
    "1. `QRealizeIntExprNode` 类继承自 `QRealizeExprNode` 类，表示一个量化整数表达式节点。它包含三个成员变量：`dom_scale`、`dtype` 和 `data`，分别用于存储量化整数表达式的域缩放因子、数据类型和数据。同时，它还定义了一个静态常量字符串 `_type_key`，用于表示该类的类型信息。此外，它还使用了 `TVM_DECLARE_FINAL_OBJECT_INFO` 宏来声明基类对象的信息。\n",
    "\n",
    "2. `QRealizeIntExpr` 类继承自 `QRealizeExpr` 类，表示一个量化整数表达式。它使用了 `TVM_DLL` 宏来声明类的导出方式，并使用 `TVM_DEFINE_OBJECT_REF_METHODS` 宏来定义对象引用方法，该方法将 `QRealizeIntExpr` 类与 `QRealizeIntExprNode` 类关联起来。这样，可以通过 `QRealizeIntExpr` 对象间接访问和操作 `QRealizeIntExprNode` 对象。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `QRealizeIntExprNode::Realize` & `QRealizeIntExpr::QRealizeIntExpr`\n",
    "\n",
    "```c++\n",
    "Expr QRealizeIntExprNode::Realize() const {\n",
    "  Expr data = this->data;\n",
    "  // dequantize\n",
    "  data = Cast(data, DataType::Float(32));\n",
    "  data = Multiply(data, this->dom_scale);\n",
    "  return data;\n",
    "}\n",
    "\n",
    "QRealizeIntExpr::QRealizeIntExpr(Expr data, Expr dom_scale, DataType dtype) {\n",
    "  ObjectPtr<QRealizeIntExprNode> n = make_object<QRealizeIntExprNode>();\n",
    "  n->data = std::move(data);\n",
    "  n->dom_scale = std::move(dom_scale);\n",
    "  n->dtype = std::move(dtype);\n",
    "  data_ = std::move(n);\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是两个C++函数的定义，它们分别表示量化整数表达式节点的实现和量化整数表达式的构造函数。\n",
    "\n",
    "1. `QRealizeIntExprNode::Realize()` 函数是量化整数表达式节点的实现函数，它首先将数据类型转换为浮点数，然后将数据乘以域缩放因子，最后返回结果。\n",
    "\n",
    "2. `QRealizeIntExpr::QRealizeIntExpr()` 函数是量化整数表达式的构造函数，它创建一个 `QRealizeIntExprNode` 对象，并将传入的数据、域缩放因子和数据类型赋值给该对象的成员变量，最后将该对象赋值给 `data_` 成员变量。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 自动量化 ForwardOp\n",
    "\n",
    "```c++\n",
    "inline Expr ForwardOp(const Call& ref_call, const Array<Expr>& args) {\n",
    "  return Call(ref_call->op, args, ref_call->attrs, ref_call->type_args);\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这是一个C++函数，名为`ForwardOp`，它接受两个参数：类型为 `Call` 的常量引用 `ref_call` 和类型为 `Array<Expr>` 的常量引用 `args`。函数的返回类型是 `Expr`。\n",
    "\n",
    "函数的主要作用是将`ref_call`中的算子、属性和类型参数传递给新的 `Call` 对象，并将 `args` 作为新对象的参数。最后，返回这个新的 `Call` 对象。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py312x",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
